package com.cai.xiaobai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cai.xiaobai.entity.AnswerInfo;
import com.cai.xiaobai.entity.AnswerOptionContent;
import com.cai.xiaobai.entity.DTO.fromInfo.addFrom.AddFromDTO;
import com.cai.xiaobai.entity.FromInfo;
import com.cai.xiaobai.entity.OptionInfo;
import com.cai.xiaobai.entity.QuestionInfo;
import com.cai.xiaobai.entity.VO.fromInfo.getFromInfo.GetFromInfoVO;
import com.cai.xiaobai.entity.VO.fromInfo.getFromInfo.OptionInfoVO;
import com.cai.xiaobai.entity.VO.fromInfo.getMyFrom.GetMyFromVO;
import com.cai.xiaobai.enums.QuestionTypeEnum;
import com.cai.xiaobai.mapper.FromInfoMapper;
import com.cai.xiaobai.result.R;
import com.cai.xiaobai.result.Result;
import com.cai.xiaobai.result.ResultCode;
import com.cai.xiaobai.service.IAnswerInfoService;
import com.cai.xiaobai.service.IFromInfoService;
import com.cai.xiaobai.service.IOptionInfoService;
import com.cai.xiaobai.service.IQuestionInfoService;
import com.cai.xiaobai.utils.SnowFlow;
import com.cai.xiaobai.utils.common.Func;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 调查问卷表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-05-13
 */
@Service
@AllArgsConstructor
public class FromInfoServiceImpl extends ServiceImpl<FromInfoMapper, FromInfo> implements IFromInfoService {
    private final IQuestionInfoService iQuestionInfoService;
    private final IOptionInfoService iOptionInfoService;
    private final IAnswerInfoService iAnswerInfoService;

    @Override
    @Transactional
    public Result addFrom(AddFromDTO addFromDTO) {
        if (addFromDTO.getQuestionList().isEmpty()) {
            return R.Fail(ResultCode.FORBIDDEN, "数据不全");
        }
        SnowFlow snowFlow = new SnowFlow(1, 1);
        long fromId = snowFlow.nextId();
        List<QuestionInfo> questionInfoList = new ArrayList<>();
        List<OptionInfo> optionInfoList = new ArrayList<>();
        addFromDTO.getQuestionList().forEach(questionDTO -> {
            QuestionInfo questionInfo = new QuestionInfo();
            BeanUtils.copyProperties(questionDTO, questionInfo);
            questionInfo.setQuestionFlag(questionDTO.getQuestionFlag() ? 1 : 0);
            questionInfo.setFormId(fromId);
            long questionId = snowFlow.nextId();
            questionInfo.setId(questionId);
            questionInfoList.add(questionInfo);
            if (!Objects.isNull(questionDTO.getOptionList()) && !(questionDTO.getOptionList().isEmpty())) {
                questionDTO.getOptionList().forEach(optionDTO -> {
                    OptionInfo optionInfo = new OptionInfo();
                    BeanUtils.copyProperties(optionDTO, optionInfo);
                    optionInfo.setFromId(fromId);
                    optionInfo.setQuestionId(questionId);
                    optionInfoList.add(optionInfo);
                });
            }
        });
        FromInfo fromInfo = new FromInfo();
        fromInfo.setId(fromId);
        fromInfo.setCreateUser(addFromDTO.getOpenId());
        fromInfo.setCreateTime(LocalDateTime.now());
        BeanUtils.copyProperties(addFromDTO, fromInfo);

        boolean flag;
        if (optionInfoList.isEmpty()) {
            flag = this.save(fromInfo) && iQuestionInfoService.saveBatch(questionInfoList);
        } else {
            flag = this.save(fromInfo) && iQuestionInfoService.saveBatch(questionInfoList) && iOptionInfoService.saveBatch(optionInfoList);
        }
        if (flag) {
            return R.Success("创建成功");
        } else {
            return R.Fail(ResultCode.INTERNAL_SERVER_ERROR, "创建失败请联系管理人员");
        }
    }

    @Override
    public Result getMyFrom(String openId, String status, Boolean flag) {
        LambdaQueryWrapper<FromInfo> lambda = new QueryWrapper<FromInfo>().lambda();
        if (!Objects.isNull(openId)) {
            lambda.eq(FromInfo::getCreateUser, openId)
                .orderByAsc(FromInfo::getSort);
            List<Object> formIdList = iAnswerInfoService.listObjs(new LambdaQueryWrapper<AnswerInfo>()
                .eq(AnswerInfo::getOpenId, openId)
                .select(AnswerInfo::getFromId));
            if (flag) {
                lambda.in(FromInfo::getId, formIdList);
            }
        }
        if (!Objects.isNull(status)) {
            lambda.eq(FromInfo::getStatus, status);
        }



        List<FromInfo> fromInfoList = this.list(lambda);
        if (fromInfoList.isEmpty()) {
            return R.Success(null);
        }
        List<Long> formIdList = fromInfoList.stream().map(FromInfo::getId).toList();
        Map<Long, Long> map = iAnswerInfoService.getFromAnswerNumber(formIdList);
        List<GetMyFromVO> getMyFromVOS = new ArrayList<>();
        fromInfoList.forEach(fromInfo -> {
            GetMyFromVO getMyFromVO = new GetMyFromVO();
            BeanUtils.copyProperties(fromInfo, getMyFromVO);
            getMyFromVO.setNumber(Objects.isNull(map.get(getMyFromVO.getId())) ? 0 : Math.toIntExact(map.get(getMyFromVO.getId())));
            getMyFromVOS.add(getMyFromVO);
        });

        return R.Success(getMyFromVOS);
    }

    @Override
    public Result delete(String ids) {
        List<String> list = Arrays.asList(ids.split(","));
        boolean remove = this.remove(new QueryWrapper<FromInfo>().lambda()
            .in(FromInfo::getId, list));
        boolean remove1 = iQuestionInfoService.remove(new LambdaQueryWrapper<QuestionInfo>()
            .in(QuestionInfo::getFormId, list));
        boolean remove2 = iOptionInfoService.remove(new LambdaQueryWrapper<OptionInfo>()
            .in(OptionInfo::getFromId, list));
        boolean remove3 = iAnswerInfoService.remove(new LambdaQueryWrapper<AnswerInfo>()
            .in(AnswerInfo::getFromId, list));
        return R.Success(remove && remove1 && remove2 && remove3);
    }

    @Override
    public Result getFromInfo(String fromId) {
        FromInfo one = this.getOne(new LambdaQueryWrapper<FromInfo>().eq(FromInfo::getId, fromId), false);
        if (one == null) {
            return R.Fail(ResultCode.INTERNAL_SERVER_ERROR, "该问卷未查询到请重试,或者联系管理人员");
        }
        List<QuestionInfo> list = iQuestionInfoService.list(new LambdaQueryWrapper<QuestionInfo>()
            .eq(QuestionInfo::getFormId, fromId)
            .orderByAsc(QuestionInfo::getQuestionSort));
        if (list.isEmpty()) {
            return R.Fail(ResultCode.INTERNAL_SERVER_ERROR, "该问卷当中未有问题数据,如若有错误请联系管理人员");
        }
        List<Long> questionInfoList = list.stream()
            .filter(questionInfo -> !Objects.equals(questionInfo.getQuestionType(), QuestionTypeEnum.FILL_A_VACANCY.getKey()))
            .map(QuestionInfo::getId).toList();
//        拿到选项当中的数据id
        Map<Long, List<OptionInfoVO>> optionInfoMap;
        if (Func.isNotEmpty(questionInfoList)) {
            optionInfoMap = iOptionInfoService.getOptionMap(questionInfoList);
        } else {
            optionInfoMap = null;
        }
//        判断如果需要拿答案就把答案一下返回
        boolean flag;
        Map<Long, AnswerOptionContent> answerOptionContentMap;
        answerOptionContentMap = iAnswerInfoService.getFromAnswerInfo(fromId);
        flag = !Func.isNull(answerOptionContentMap);
        List<GetFromInfoVO> voArrayList = new ArrayList<>();

        list.forEach(questionInfo -> {
            GetFromInfoVO getFromInfoVO = new GetFromInfoVO();
            BeanUtils.copyProperties(questionInfo, getFromInfoVO);
            getFromInfoVO.setQuestionFlag(questionInfo.getQuestionFlag() == 1);
            getFromInfoVO.setOptionList(Func.isNull(optionInfoMap) ? null : optionInfoMap.get(getFromInfoVO.getId()));
            if (flag) {
                AnswerOptionContent content = answerOptionContentMap.get(questionInfo.getId());
                getFromInfoVO.setAnswer(Func.isNull(content.getOptionId()) ? content.getOptionContent() : content.getOptionId());
            }
            voArrayList.add(getFromInfoVO);
        });
        return R.Success(voArrayList);
    }

}
